package com.promise.jokerdream.work.penguin

import com.promise.jokerdream.database.entity.ExperienceGameConfigEntity
import com.promise.jokerdream.config.game.ExperiencePriorityType
import com.promise.jokerdream.manager.ExecutionHistoryManager
import com.promise.jokerdream.model.misty.MistyMapping
import com.promise.jokerdream.repository.GameApi
import com.promise.jokerdream.repository.foldWithApiException
import com.promise.jokerdream.utils.AppContext
import com.promise.jokerdream.work.BaseWork
import com.promise.jokerdream.work.WorkResult

// 企鹅历练工作
class PenguinExperienceWork(
    private val config: ExperienceGameConfigEntity,
    uin: String
): BaseWork(uin) {

    private val gameApi = GameApi.Companion.getInstance()
    private val historyManager by lazy { ExecutionHistoryManager.Companion.getInstance(AppContext.get()) }
    
    // 记录已经尝试过的药水索引
    private var usedPotionIndex = 0
    
    // 药水配置，分别是活力药水、小活力药水
    private val potionIds = listOf("3105", "3386")


    override val name: String
        get() = "历练"

    override suspend fun executeWork(): WorkResult {
        // 根据配置确定历练顺序
        val mapOrder = getMapOrder()
        
        // 遍历每个地图
        for (mapId in mapOrder) {
            // 执行挑战循环
            val result = executeFightLoop(mapId)
            if (result is WorkResult.Failure) {
                return result
            }
        }

        return WorkResult.Success
    }
    
    /**
     * 挑战前检查活力值
     */
    private suspend fun checkVitalityBeforeFight(): WorkResult {
        val penguinInfoResult = gameApi.queryPenguinInfo(uin)
        return penguinInfoResult.foldWithApiException(
            onSuccess = { response ->
                val currentVitality = response.baseInfo.energy
                if (currentVitality < 10) {
                    // 活力值不足，检查是否可以使用药水
                    if (config.useVitalityPotion && usedPotionIndex < potionIds.count()) {
                        // 有药水可用，先使用药水
                        val useResult = usePotionBeforeFight()
                        if (useResult is WorkResult.Failure) {
                            return useResult
                        }
                        WorkResult.Success
                    } else {
                        // 没有药水可用或已用完，直接返回失败
                        val message = "活力值不足($currentVitality/10)，且无可用药水"
                        WorkResult.Failure(Exception(message), message)
                    }
                } else {
                    // 活力值充足
                    WorkResult.Success
                }
            },
            onFailure = { code, msg ->
                historyManager.addHistory(name, msg, code)
                WorkResult.Failure(Exception(msg), msg)
            }
        )
    }
    
    /**
     * 执行单次挑战（包含活力值检查和结果处理）
     */
    private suspend fun executeSingleFight(monsterId: Int): WorkResult {
        // 挑战前检查活力值
        val vitalityCheckResult = checkVitalityBeforeFight()
        if (vitalityCheckResult is WorkResult.Failure) {
            return vitalityCheckResult
        }
        
        // 执行挑战
        val fightResult = gameApi.mapPushFight(monsterId)
        return fightResult.foldWithApiException(
            onSuccess = { fightResponse ->
                historyManager.addHistory(name, fightResponse.getDescription())
                WorkResult.Success
            },
            onFailure = { code, msg ->
                historyManager.addHistory(name, msg, code)
                WorkResult.Failure(Exception(msg), msg)
            }
        )
    }
    
    /**
     * 执行挑战循环
     */
    private suspend fun executeFightLoop(mapId: Int): WorkResult {
        val queryResult = gameApi.queryMapPush(mapId)
        return queryResult.foldWithApiException(
            onSuccess = { response ->
                val lastBoss = response.monsterInfos.lastOrNull()
                if (lastBoss != null && lastBoss.challengeTimes > 0) {
                    // 有挑战次数，循环挑战
                    repeat(lastBoss.challengeTimes) { attempt ->
                        val fightResult = executeSingleFight(lastBoss.monsterId)
                        if (fightResult is WorkResult.Failure) {
                            // 挑战失败，直接结束
                            return fightResult
                        }
                    }
                }
                WorkResult.Success
            },
            onFailure = { code, msg ->
                historyManager.addHistory(name, msg, code)
                WorkResult.Success // 查询失败不影响整体流程
            }
        )
    }
    
    /**
     * 挑战前使用药水
     */
    private suspend fun usePotionBeforeFight(): WorkResult {
        if (usedPotionIndex >= potionIds.size) {
            return WorkResult.Failure(Exception("无可用药水"), "无可用药水")
        }
        
        val potionId = potionIds[usedPotionIndex]
        val useResult = gameApi.useGoods(uin, potionId)
        return useResult.foldWithApiException(
            onSuccess = { response ->
                historyManager.addHistory(name, response.getDescription())
                WorkResult.Success
            },
            onFailure = { code, msg ->
                // 该物品今天已经不能再使用了，不用标红
                historyManager.addHistory(name, msg, if (code != -1) code else 0)
                usedPotionIndex++
                // 尝试下一个药水
                if (usedPotionIndex < potionIds.size) {
                    usePotionBeforeFight()
                } else {
                    WorkResult.Failure(Exception("无可用药水"), "无可用药水")
                }
            }
        )
    }
    
    /**
     * 根据配置获取地图顺序
     */
    private fun getMapOrder(): List<Int> {
        val priorityType = try { ExperiencePriorityType.valueOf(config.priorityType) } catch (e: Exception) { ExperiencePriorityType.EXPERIENCE }
        return when (priorityType) {
            ExperiencePriorityType.EXPERIENCE -> {
                // 经验优先：MistyMapping.mapIdToMapInfo倒序
                MistyMapping.getAllMapIds().reversed()
            }
            ExperiencePriorityType.VITALITY_POTION -> {
                // 天赋丹优先：玉龙雪山到林松郊外，然后剩下的倒序
                val priorityMaps = (10 downTo 2).toList() // 玉龙雪山(10)到林松郊外(2)
                val remainingMaps = MistyMapping.getAllMapIds().filter { it !in priorityMaps }.reversed()
                priorityMaps + remainingMaps
            }
            ExperiencePriorityType.CUSTOM_ORDER -> {
                // 自定义顺序：按选中的顺序，然后剩下的排除选中的后倒序
                val customOrderList = if (config.customOrder.isEmpty()) {
                    emptyList()
                } else {
                    config.customOrder.split(",").mapNotNull { it.trim().toIntOrNull() }
                }
                val remainingMaps = MistyMapping.getAllMapIds().filter { it !in customOrderList }.reversed()
                customOrderList + remainingMaps
            }
        }
    }
}